package zmee.pmpt.formplugin;

import kd.bos.bill.AbstractBillPlugIn;
import kd.bos.dataentity.entity.DynamicObject;
import kd.bos.dataentity.entity.DynamicObjectCollection;
import kd.bos.dataentity.resource.ResManager;
import kd.bos.dataentity.utils.StringUtils;
import kd.bos.form.FormShowParameter;
import kd.bos.form.ShowType;
import kd.bos.form.chart.*;
import kd.bos.form.control.EntryGrid;
import kd.bos.form.control.events.ChartClickEvent;
import kd.bos.form.events.AfterDoOperationEventArgs;
import kd.bos.form.events.HyperLinkClickEvent;
import kd.bos.form.events.HyperLinkClickListener;
import kd.bos.orm.query.QFilter;
import kd.bos.servicehelper.BusinessDataServiceHelper;
import kd.pccs.placs.common.enums.CompletionStatusEnum;
import kd.pccs.placs.common.utils.DateUtil;
import kd.pccs.placs.common.utils.ext.MetaDataUtil;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;

/**
 * @Author: zyj
 * @Date: 2023/8/4 17:31
 * @Description: 项目计划达成率单: 点击跳转相应超链接，根据数据画出柱状图
 */
public class ProplanrateBillPlugin extends AbstractBillPlugIn implements HyperLinkClickListener {

    @Override
    public void registerListener(EventObject e) {
        super.registerListener(e);
        Chart totalChart = (Chart)this.getControl("histogramchartap");
        totalChart.addClickListener(this);
        EntryGrid entryGrid = (EntryGrid)this.getControl("entryentity");
        entryGrid.addHyperClickListener(this);
    }

    @Override
    public void afterBindData(EventObject e) {
        super.afterBindData(e);
        DynamicObject dataEntity = this.getModel().getDataEntity(true);
        // 获取数据明细单据体
        DynamicObjectCollection dataDetail = dataEntity.getDynamicObjectCollection("entryentity");
        // 如果数据明细单据体不为空，加载柱状图
        if (dataDetail != null && dataDetail.size() != 0) {
            loadHistogramchartap();
        }
    }

    /**
     * 加载柱状图
     */
    public void loadHistogramchartap() {
        // 获取单据对象
        DynamicObject dataEntity = this.getModel().getDataEntity(true);
        // 获取数据明细单据体
        DynamicObjectCollection entryentities = dataEntity.getDynamicObjectCollection("entryentity");
        // 存放按时完成数量
        List<Integer> onTimeEndList = new ArrayList(10);
        // 存放逾期完成数量
        List<Integer> overTimeEndList = new ArrayList(10);
        // 存放逾期未完成数量
        List<Integer> overTimeNotEndList = new ArrayList(10);
        // 存放完成率
        List<BigDecimal> endRateList = new ArrayList(10);
        // 存放项目名称
        List<String> projectNameList = new ArrayList(10);
        for (DynamicObject entryentity : entryentities) {
            onTimeEndList.add(entryentity.getInt("ontimeend"));
            overTimeEndList.add(entryentity.getInt("overtimeend"));
            overTimeNotEndList.add(entryentity.getInt("overtimenotend"));
            projectNameList.add(entryentity.getDynamicObject("project").getString("name"));
            // 计划完成数量
            int planend = entryentity.getInt("planend");
            Integer totalEnd = entryentity.getInt("ontimeend") + entryentity.getInt("overtimeend");
            BigDecimal endRate = BigDecimal.ZERO;
            if (planend != 0) {
                // 完成率 = （按时完成数量 + 逾期完成数量）/ 计划完成数量
                endRate = BigDecimal.valueOf((long)totalEnd).divide(BigDecimal.valueOf((long)planend), 4, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100L));
            }
            endRateList.add(endRate);
        }
        // 绘制柱状图
        this.setHistogramChart(onTimeEndList, overTimeEndList, overTimeNotEndList, endRateList, projectNameList);
    }

    @Override
    public void click(EventObject evt) {
        super.click(evt);
        String sourceName = evt.getSource().getClass().getName();
        if (StringUtils.equals(sourceName, HistogramChart.class.getName())) {
            ChartClickEvent chartClickEvent = (ChartClickEvent)evt;
            Chart chart = chartClickEvent.getSource();
            if (StringUtils.equals("histogramchartap", chart.getKey())) {
                this.gramChartapClick(chartClickEvent);
            }
        }

    }

    // 标准产品
    protected void gramChartapClick(ChartClickEvent chartClickEvent) {
        String projectName = chartClickEvent.getName();
        String seriesName = chartClickEvent.getSeriesName();
        if (projectName != null && seriesName != null) {
            if (!seriesName.contains("%")) {
                DynamicObject project = this.getProjectByName(projectName);
                if (project == null) {
                    this.getView().showTipNotification(ResManager.loadKDString("点击的项目的数据已经被删除，请重新查询数据后再操作。", "ProPlanReachRatePlugin_14", "pccs-placs-formplugin", new Object[0]));
                } else {
                    String completionStatus = "";
                    if (StringUtils.equals(seriesName, CompletionStatusEnum.OVERDUECOMPLETE.getName())) {
                        completionStatus = CompletionStatusEnum.OVERDUECOMPLETE.getValue();
                    } else if (StringUtils.equals(seriesName, ResManager.loadKDString("逾期未完成", "ProPlanReachRatePlugin_5", "pccs-placs-formplugin", new Object[0]))) {
                        completionStatus = CompletionStatusEnum.OVERDUE.getValue();
                    } else if (StringUtils.equals(seriesName, CompletionStatusEnum.ONTIMECOMPLETE.getName())) {
                        completionStatus = CompletionStatusEnum.ONTIMECOMPLETE.getValue();
                    }

                    if (StringUtils.isBlank(completionStatus)) {
                        this.getView().showTipNotification(ResManager.loadKDString("点击的图块的状态与系统任务状态不匹配，请联系管理员。", "ProPlanReachRatePlugin_15", "pccs-placs-formplugin", new Object[0]));
                    } else {
                        Map<String, Object> paramMap = new HashMap();
                        DynamicObject dataEntity = this.getModel().getDataEntity();
                        Set<Object> controlLevelIdSet = this.getControlLevelSet(dataEntity);
                        if (!controlLevelIdSet.isEmpty()) {
                            paramMap.put("controllevels", controlLevelIdSet);
                        }

                        Set<Object> taskTypeIdSet = this.getTaskTypeIdSet(dataEntity);
                        if (!taskTypeIdSet.isEmpty()) {
                            paramMap.put("tasktypes", taskTypeIdSet);
                        }

                        Set<Object> taskSourceIdSet = this.getTaskSourceIdSet(dataEntity);
                        if (!taskSourceIdSet.isEmpty()) {
                            paramMap.put("tasksource", taskSourceIdSet);
                        }

                        paramMap.put("daterange_startdate", this.getRangeBeginDate(dataEntity));
                        paramMap.put("daterange_enddate", this.getRangeEndDate(dataEntity));
                        paramMap.put("formId", this.getAppId() + "_tasklist");
                        paramMap.put("projectId", project.getString("id"));
                        paramMap.put("completionStatus", completionStatus);
                        paramMap.put("billsource", MetaDataUtil.getEntityId(this.getAppId(), "proplanreachrate"));
                        FormShowParameter showParameter = FormShowParameter.createFormShowParameter(paramMap);
                        showParameter.setAppId(this.getAppId());
                        showParameter.getOpenStyle().setShowType(ShowType.MainNewTabPage);
                        this.getView().showForm(showParameter);
                    }
                }
            }
        }
    }

    @Override
    public void afterDoOperation(AfterDoOperationEventArgs e) {
        super.afterDoOperation(e);
        super.afterDoOperation(e);
        String operateKey = e.getOperateKey();
        if ("generatehistogram".equals(operateKey)) {
            loadHistogramchartap();
        }
    }

    // 标准产品
    protected void setHistogramChart(List<Integer> onTimeEndList, List<Integer> overTimeEndList, List<Integer> overTimeNotEndList, List<BigDecimal> endRateList, List<String> projectNameList) {
        for(int i = projectNameList.size(); i < 8; ++i) {
            projectNameList.add("");
        }

        HistogramChart histogramChart = (HistogramChart)this.getControl("histogramchartap");
        histogramChart.clearData();
        Axis xAxis = histogramChart.createXAxis("", projectNameList);
        if (projectNameList.size() > 8) {
            Map<String, Object> axisLabelMap = new HashMap();
            axisLabelMap.put("interval", 0);
            axisLabelMap.put("rotate", -40);
            xAxis.setPropValue("axisLabel", axisLabelMap);
        }

        kd.bos.form.chart.Label plLabel = new kd.bos.form.chart.Label();
        plLabel.setShow(true);
        plLabel.setFontSize("14");
        plLabel.setPosition(Position.inside);
        histogramChart.createYAxis(ResManager.loadKDString("任务数", "ProPlanReachRatePlugin_17", "pccs-placs-formplugin", new Object[0]), AxisType.value);
        BarSeries series = histogramChart.createBarSeries(ResManager.loadKDString("按时完成", "ProPlanReachRatePlugin_2", "pccs-placs-formplugin", new Object[0]));
        series.setBarWidth("50px");
        series.setStack("aa");
        series.setData((Number[])onTimeEndList.toArray(new Integer[onTimeEndList.size()]));
        series.setColor("#83F348");
        series.setLabel(plLabel);
        BarSeries series1 = histogramChart.createBarSeries(ResManager.loadKDString("逾期完成", "ProPlanReachRatePlugin_3", "pccs-placs-formplugin", new Object[0]));
        series1.setBarWidth("50px");
        series1.setStack("aa");
        series1.setData((Number[])overTimeEndList.toArray(new Integer[overTimeEndList.size()]));
        series1.setColor("#2DECE9");
        series1.setLabel(plLabel);
        BarSeries series2 = histogramChart.createBarSeries(ResManager.loadKDString("逾期未完成", "ProPlanReachRatePlugin_5", "pccs-placs-formplugin", new Object[0]));
        series2.setBarWidth("50px");
        series2.setStack("aa");
        series2.setData((Number[])overTimeNotEndList.toArray(new Integer[overTimeNotEndList.size()]));
        series2.setColor("#FF585A");
        series2.setLabel(plLabel);
        Axis yAxis2 = histogramChart.createYAxis(ResManager.loadKDString("完成率", "ProPlanReachRatePlugin_8", "pccs-placs-formplugin", new Object[0]), AxisType.value);
        Map<String, Object> map = new HashMap();
        map.put("formatter", "{value}%");
        yAxis2.setPropValue("axisLabel", map);
        yAxis2.setInterval(20);
        yAxis2.setMax(100);
        LineSeries lineSeries = histogramChart.createLineSeries(ResManager.loadKDString("完成率（%）", "ProPlanReachRatePlugin_18", "pccs-placs-formplugin", new Object[0]));
        lineSeries.setData((Number[])endRateList.toArray(new BigDecimal[endRateList.size()]));
        Map<String, Object> itemStyleMap = new HashMap();
        Map<String, Object> normalMap = new HashMap();
        normalMap.put("color", "#1A94E6");
        itemStyleMap.put("normal", normalMap);
        lineSeries.setPropValue("itemStyle", itemStyleMap);
        lineSeries.setYAxisIndex(1);
        histogramChart.setShowTooltip(true);
        histogramChart.setShowLegend(true);
        histogramChart.setShowTitle(false);
        histogramChart.refresh();
    }

    @Override
    public void hyperLinkClick(HyperLinkClickEvent hyperLinkClickEvent) {
        String fieldName = hyperLinkClickEvent.getFieldName();
        int rowIndex = hyperLinkClickEvent.getRowIndex();
        if (StringUtils.equals("planend", fieldName)) {
            this.showProjecTask(fieldName, rowIndex);
        } else if (StringUtils.equals("ontimeend", fieldName)) {
            this.showProjecTask(fieldName, rowIndex);
        } else if (StringUtils.equals("overtimeend", fieldName)) {
            this.showProjecTask(fieldName, rowIndex);
        } else if (StringUtils.equals("overtimenotend", fieldName)) {
            this.showProjecTask(fieldName, rowIndex);
        }
    }

    // 标准产品
    private void showProjecTask(String fieldName, int rowIndex) {
        DynamicObject project = (DynamicObject)this.getModel().getValue("project", rowIndex);
        project = this.getProjectByName(project);
        if (project == null) {
            this.getView().showTipNotification(ResManager.loadKDString("点击的项目的数据已经被删除，请重新查询数据后再操作。", "ProPlanReachRatePlugin_14", "pccs-placs-formplugin", new Object[0]));
        } else {
            String completionStatus = "";
            if (StringUtils.equals(fieldName, "ontimeend")) {
                completionStatus = CompletionStatusEnum.ONTIMECOMPLETE.getValue();
            } else if (StringUtils.equals(fieldName, "overtimeend")) {
                completionStatus = CompletionStatusEnum.OVERDUECOMPLETE.getValue();
            } else if (StringUtils.equals(fieldName, "overtimenotend")) {
                completionStatus = CompletionStatusEnum.OVERDUE.getValue();
            }

            Map<String, Object> paramMap = new HashMap();
            DynamicObject dataEntity = this.getModel().getDataEntity();
            Set<Object> controlLevelIdSet = this.getControlLevelSet(dataEntity);
            if (!controlLevelIdSet.isEmpty()) {
                paramMap.put("controllevels", controlLevelIdSet);
            }

            Set<Object> taskTypeIdSet = this.getTaskTypeIdSet(dataEntity);
            if (!taskTypeIdSet.isEmpty()) {
                paramMap.put("tasktypes", taskTypeIdSet);
            }

            Set<Object> taskSourceIdSet = this.getTaskSourceIdSet(dataEntity);
            if (!taskSourceIdSet.isEmpty()) {
                paramMap.put("tasksource", taskSourceIdSet);
            }

            paramMap.put("daterange_startdate", this.getRangeBeginDate(dataEntity));
            paramMap.put("daterange_enddate", this.getRangeEndDate(dataEntity));


            paramMap.put("formId", this.getAppId() + "_tasklist");
            paramMap.put("projectId", project.getString("id"));
            paramMap.put("completionStatus", completionStatus);
            paramMap.put("billsource", MetaDataUtil.getEntityId(this.getAppId(), "proplanreachrate"));
            FormShowParameter showParameter = FormShowParameter.createFormShowParameter(paramMap);
            showParameter.setAppId(this.getAppId());
            showParameter.getOpenStyle().setShowType(ShowType.MainNewTabPage);
            this.getView().showForm(showParameter);
        }
    }

    protected DynamicObject getProjectByName(DynamicObject project) {
        String projectName = project.getString("name");
        return BusinessDataServiceHelper.loadSingle(this.getProjectFormId(), "id", new QFilter[]{new QFilter("name", "=", projectName)});
    }

    protected DynamicObject getProjectByName(String projectName) {
        return BusinessDataServiceHelper.loadSingle(this.getProjectFormId(), "id", new QFilter[]{new QFilter("name", "=", projectName)});
    }

    protected String getProjectFormId() {
        return "bd_project";
    }

    public String getAppId() {
        return "pmpt";
    }

    protected Set<Object> getControlLevelSet(DynamicObject thisModel) {
        DynamicObjectCollection controlLevelCol = thisModel.getDynamicObjectCollection("controllevels");
        Set<Object> controlLevelIdSet = new HashSet();
        if (controlLevelCol != null && controlLevelCol.size() > 0) {
            Iterator var4 = controlLevelCol.iterator();

            while(var4.hasNext()) {
                DynamicObject dynamicObject = (DynamicObject)var4.next();
                DynamicObject controlLevel = dynamicObject.getDynamicObject("fbasedataid");
                if (controlLevel != null) {
                    controlLevelIdSet.add(controlLevel.getPkValue());
                }
            }
        }

        return controlLevelIdSet;
    }

    protected Set<Object> getTaskTypeIdSet(DynamicObject thisModel) {
        Set<Object> taskTypeIdSet = new HashSet();
        DynamicObjectCollection taskTypeCol = thisModel.getDynamicObjectCollection("tasktypes");
        if (taskTypeCol != null && taskTypeCol.size() > 0) {
            Iterator var4 = taskTypeCol.iterator();

            while(var4.hasNext()) {
                DynamicObject dynamicObject = (DynamicObject)var4.next();
                DynamicObject taskType = dynamicObject.getDynamicObject("fbasedataid");
                if (taskType != null) {
                    taskTypeIdSet.add(taskType.getPkValue());
                }
            }
        }

        return taskTypeIdSet;
    }

    protected Set<Object> getTaskSourceIdSet(DynamicObject dataEntity) {
        Set<Object> taskSourceIdSet = new HashSet();
        DynamicObjectCollection taskSourceCol = dataEntity.getDynamicObjectCollection("tasksource");
        if (taskSourceCol != null && !taskSourceCol.isEmpty()) {
            Iterator var4 = taskSourceCol.iterator();

            while(var4.hasNext()) {
                DynamicObject taskSourceObj = (DynamicObject)var4.next();
                DynamicObject taskSource = taskSourceObj.getDynamicObject("fbasedataid");
                if (taskSource != null) {
                    taskSourceIdSet.add(taskSource.getPkValue());
                }
            }
        }

        return taskSourceIdSet;
    }

    /**
     * 获取开始日期
     * @param dataEntity 单据对象
     * @return 开始日期
     */
    protected Date getRangeBeginDate(DynamicObject dataEntity) {
        boolean thisWeek = dataEntity.getBoolean("thisweek");
        boolean thisMonth = dataEntity.getBoolean("thisMonth");
        boolean threeMonth = dataEntity.getBoolean("threeMonth");
        Date nowDate = new Date();
        Date firstDayOfRange;
        if (thisWeek) {
            firstDayOfRange = DateUtil.getThisWeekMonday(nowDate);
            return firstDayOfRange;
        } else if (thisMonth) {
            firstDayOfRange = DateUtil.getFirstDayOfThisMonth(nowDate);
            return firstDayOfRange;
        } else if (threeMonth) {
            firstDayOfRange = DateUtil.getFirstDayOfPreMonth(nowDate);
            Date firstDayOfPreTwoMonth = DateUtil.getFirstDayOfPreMonth(firstDayOfRange);
            return firstDayOfPreTwoMonth;
        } else {
            firstDayOfRange = dataEntity.getDate("daterange_startdate");
            return firstDayOfRange;
        }
    }

    /**
     * 获取结束日期
     * @param dataEntity 单据对象
     * @return 结束日期
     */
    protected Date getRangeEndDate(DynamicObject dataEntity) {
        boolean thisWeek = dataEntity.getBoolean("thisweek");
        boolean thisMonth = dataEntity.getBoolean("thisMonth");
        boolean threeMonth = dataEntity.getBoolean("threeMonth");
        Date nowDate = new Date();
        Date lastDayOfRange;
        if (thisWeek) {
            lastDayOfRange = DateUtil.getThisWeekSunDay(nowDate);
            return lastDayOfRange;
        } else if (thisMonth) {
            lastDayOfRange = DateUtil.getLastDayOfThisMonth(nowDate);
            return lastDayOfRange;
        } else if (threeMonth) {
            lastDayOfRange = DateUtil.getLastDayOfThisMonth(nowDate);
            return lastDayOfRange;
        } else {
            lastDayOfRange = dataEntity.getDate("daterange_enddate");
            return lastDayOfRange;
        }
    }
}
